package net.pws.common.persistence;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import net.pws.common.persistence.hibernate3.HibernateEntityManager;

import org.hibernate.Session;
import org.springframework.jdbc.core.RowMapper;


/**
 * @see HibernateEntityManager
 */
public interface EntityManager {

    /**
     * 保存entity,如果数据库中没有对应的记录,则直接插入一条新的记录,如果数据库中已经有对应的记录,则直接更新
     * 
     * @param o
     * @see Session#saveOrUpdate(Object)
     */
    public Serializable save(Object o);
    
    
    /**
     * 保存一组对象,如果数据库中没有对应的记录,则直接插入一条新的记录,如果数据库中已经有对应的记录,则直接更新
     * 
     * @param o
     * @see Session#saveOrUpdate(Object)
     */
    @SuppressWarnings("rawtypes")
    public void save(Collection os);

    /**
     * 保存entity,如果数据库中没有对应的记录,则直接插入一条新的记录,如果数据库中已经有对应的记录,则直接更新
     * 
     * @param o
     * @see Session#saveOrUpdate(Object)
     */
    public void update(Object o);
    
    /**
     * 保存entity,如果数据库中没有对应的记录,则直接插入一条新的记录,如果数据库中已经有对应的记录,则直接更新
     * 
     * @param o
     * @see Session#saveOrUpdate(Object)
     */
    public void persist(Object o);
    
    /**
     * 删除entity
     * 
     * @param o
     * @see Session#delete(Object)
     */
    public void remove(Object o);
    
    /**
     * 根据id删除该id对应的entity
     * 
     * @param entityClazz
     * @param id
     */
    public void removeById(Class entityClazz, Serializable id);
    
    /**
     * 在符合条件的实例存在的情况下，根据给定的实体类和标识返回持久化状态的实例。
     * <p/>
     * load还可以返回entity的代理，只有在访问entity的方法的时候才会真正触发数据库的操作，对于那些只需要维护
     * entity之间的关联关系的情况下，用load方法可以提高性能。
     * <p/>
     * load返回的entity的代理，如果该entity在数据库中不存在对应的记录，那么对该entity的属性读取操作会导致系统抛出异常。
     * 
     * @param <T>
     * @param entityClazz
     *            entity对应的类
     * @param id
     *            entity的唯一标识
     * @return
     * @see Session#load(Class, Serializable)
     */
    public <T> T getReference(Class<T> entityClazz, Serializable id);
    
    /**
     * 在符合条件的实例存在的情况下，根据给定的实体类和标识返回持久化状态的实例。如果没有对应的实例，则返回null。
     * 
     * @param <T>
     * @param entityClazz
     *            entity对应的类
     * @param id
     *            entity的唯一标识
     * @return
     * @see Session#get(Class, Serializable)
     */
    public <T> T find(Class<T> entityClazz, Serializable id);
    
    /**
     * 刷新entity
     * <p/>
     * 当用户通过查询获取某个entity的实例，在这个时候其他用户可能对该entity进行了修改并提交到数据库，
     * 当前用户可以通过本方法将数据库中已经变化的部分同步到当前实例。
     * 
     * @param entity
     *            entity实例
     * @see Session#refresh(Object)
     */
    public void refresh(Object entity);
    
    /**
     * 查找所有的entity示例
     * 
     * @param <T>
     * @param entityClazz
     *            entity对应的类
     * @return
     */
    public <T> List<T> findAll(Class<T> entityClazz);
    
    /**
     * @param unitOfWork
     * @see UnitOfWork
     */
    public void execute(UnitOfWork unitOfWork);

    /**
     * 
     * @param hql
     * @param parameters
     * @return
     */
    public int execute(final String hql, final Map parameters);
    
    /**
     * 
     * @param hql
     * @param parameters
     * @return
     */
    public int execute(String hql, Object[] parameters);
    
    /**
     * 和hibernate session flush操作效果一样
     * 
     * @see Session#flush()
     */
    public void flush();
    
    // ***********************HQL API***********************
    /**
     * 列表查询
     * <p/>
     * 根据指定的hql和查询参数（参数为Map类型的键值对集合，hql中的动态参数为命名的动态参数，例如:name）进行查询
     * 
     * @param hql
     * @param parameters
     * @return
     */
    public List findList(String hql, Map parameters);
    
    /**
     * 列表查询
     * <p/>
     * 根据指定的hql和查询参数（参数为对象数组，hql中的动态参数为?）进行查询
     * 
     * @param hql
     * @param parameters
     * @return
     */
    public List findList(String hql, Object[] parameters);
    
    /**
     * 唯一值查询
     * <p/>
     * 根据指定的hql和查询参数（参数为Map类型的键值对集合，hql中的动态参数为命名的动态参数，例如:name）进行查询。
     * <p/>
     * 查询结果为唯一值，如果实际返回的查询结果不唯一，系统会抛出异常，如果查询结果为null，则返回null。
     * 
     * @param hql
     * @param parameters
     * @return
     */
    public Object findUnique(String hql, Map parameters);
    
    /**
     * 唯一值查询
     * <p/>
     * 根据指定的hql和查询参数（参数为对象数组，hql中的动态参数为?）进行查询
     * <p/>
     * 查询结果为唯一值，如果实际返回的查询结果不唯一，系统会抛出异常，如果查询结果为null，则返回null。
     * 
     * @param hql
     * @param parameters
     * @return
     */
    public Object findUnique(String hql, Object[] parameters);
    
    /**
     * 唯一值查询
     * <p/>
     * 根据指定的hql和查询参数（参数为Map类型的键值对集合，hql中的动态参数为命名的动态参数，例如:name）进行查询。
     * <p/>
     * 返回查询结果中的第一条数据，如果查询结果为null，则返回null。
     * 
     * @param hql
     * @param parameters
     * @return
     */
    public Object findFirst(String hql, Map parameters);
    
    /**
     * 唯一值查询
     * <p/>
     * 根据指定的hql和查询参数（参数为对象数组，hql中的动态参数为?）进行查询
     * <p/>
     * 返回查询结果中的第一条数据，如果查询结果为null，则返回null。
     * 
     * @param hql
     * @param parameters
     * @return
     */
    public Object findFirst(String hql, Object[] parameters);
    
    /**
     * 分页查询
     * <p/>
     * 根据指定的hql和查询参数（参数为Map类型的键值对集合，hql中的动态参数为命名的动态参数，例如:name）进行查询，
     * 并根据查询的范围参数对查询结果进行过滤，
     * <p/>
     * 系统会自动根据指定的hql语句计算出对应的计数语句，在查询的时候对结果集进行统计（对应到Page的totalDataCount属性值）。
     * 
     * @param queryStatement
     * @param parameters
     * @param startPageNo
     * @param maxResultInPage
     * @return
     */
    public IPage findPage(String queryStatement,
                         Map parameters,
                         int startPageNo,
                         int maxResultInPage);
    
    /**
     * 分页查询
     * <p/>
     * 根据指定的hql和查询参数（参数为对象数组，hql中的动态参数为?）进行查询，并根据查询的范围参数对查询结果进行过滤，
     * <p/>
     * 系统会自动根据指定的hql语句计算出对应的计数语句，在查询的时候对结果集进行统计（对应到Page的totalDataCount属性值）。
     * 
     * @param queryStatement
     * @param parameters
     * @param startPageNo
     * @param maxResultInPage
     * @return
     */
    public IPage findPage(String queryStatement,
                         Object[] parameters,
                         int startPageNo,
                         int maxResultInPage);
    
    /**
     * 分页查询
     * <p/>
     * 根据指定的hql查询语句和查询参数（参数为Map类型的键值对集合，hql中的动态参数为命名的动态参数，例如:name）进行查询，
     * 并根据查询的范围参数对查询结果进行过滤，
     * <p/>
     * 用户必须提供hql查询语句对应的计数语句，这种场景下系统会使用用户提供的计数语句对结果集进行统计（
     * 对应到Page的totalDataCount属性值）。
     * 
     * @param queryStatement4Count
     * @param queryStatement
     * @param parameters
     * @param startPageNo
     * @param maxResultInPage
     * @return
     */
    public IPage findPage(String queryStatement4Count,
                         String queryStatement,
                         Map parameters,
                         int startPageNo,
                         int maxResultInPage);
    
    /**
     * 分页查询
     * <p/>
     * 根据指定的hql和查询参数（参数为对象数组，hql中的动态参数为?）进行查询，并根据查询的范围参数对查询结果进行过滤，
     * <p/>
     * 用户必须提供hql查询语句对应的计数语句，这种场景下系统会使用用户提供的计数语句对结果集进行统计（
     * 对应到Page的totalDataCount属性值）。
     * 
     * @param queryStatement4Count
     * @param queryStatement
     * @param parameters
     * @param startPageNo
     * @param maxResultInPage
     * @return
     */
    public IPage findPage(String queryStatement4Count,
                         String queryStatement,
                         Object[] parameters,
                         int startPageNo,
                         int maxResultInPage);
    
    // ************************SQL API***********************
    /**
     * 列表查询
     * <p/>
     * 根据指定的sql和查询参数（参数为对象数组，sql中的动态参数为?）进行查询
     * 
     * @param sql
     * @param parameters
     * @return
     */
    public List nativeFindList(String sql, Object[] parameters);
    
    /**
     * 唯一值查询
     * <p/>
     * 根据指定的sql和查询参数（参数为对象数组，sql中的动态参数为?）进行查询
     * <p/>
     * 查询结果为唯一值，如果实际返回的查询结果不唯一，系统会抛出异常，如果查询结果为null，则返回null。
     * 
     * @param sql
     * @param parameters
     * @return
     */
    public Object nativeFindUnique(String sql, Object[] parameters);
    
    /**
     * 唯一值查询
     * <p/>
     * 根据指定的sql和查询参数（参数为对象数组，sql中的动态参数为?）进行查询
     * <p/>
     * 返回查询结果中的第一条数据，如果查询结果为null，则返回null。
     * 
     * @param sql
     * @param parameters
     * @return
     */
    public Object nativeFindFirst(String sql, Object[] parameters);
    
    /**
     * 分页查询
     * <p/>
     * 根据指定的sql和查询参数（参数为对象数组，sql中的动态参数为?）进行查询，并根据查询的范围参数对查询结果进行过滤，
     * <p/>
     * 系统会自动根据指定的sql语句计算出对应的计数语句，在查询的时候对结果集进行统计（对应到Page的totalDataCount属性值）。
     * 
     * @param sql
     * @param parameters
     * @param startPageNo
     * @param maxResultInPage
     * @return
     */
    public IPage nativeFindPage(String sql,
                               Object[] parameters,
                               int startPageNo,
                               int maxResultInPage);
    
    /**
     * 分页查询
     * <p/>
     * 根据指定的sql和查询参数（参数为对象数组，sql中的动态参数为?）进行查询，并根据查询的范围参数对查询结果进行过滤，
     * <p/>
     * 用户必须提供sql查询语句对应的计数语句，这种场景下系统会使用用户提供的计数语句对结果集进行统计（
     * 对应到Page的totalDataCount属性值）。
     * 
     * @param sql4count
     * @param sql4list
     * @param parameters
     * @param startPageNo
     * @param maxResultInPage
     * @return
     */
    public IPage nativeFindPage(String sql4count,
                               String sql4list,
                               Object[] parameters,
                               int startPageNo,
                               int maxResultInPage);
    
    /**
     * 列表查询
     * <p/>
     * 根据指定的sql和查询参数（参数为对象数组，sql中的动态参数为?）进行查询
     * 
     * @param sql
     * @param parameters
     * @param rowMapper
     *            将返回的结果转化为指定的类型
     * @return
     */
    public List nativeFindList(String sql,
                               Object[] parameters,
                               RowMapper rowMapper);
    
    /**
     * 唯一值查询
     * <p/>
     * 根据指定的sql和查询参数（参数为对象数组，sql中的动态参数为?）进行查询
     * <p/>
     * 返回查询结果中的第一条数据，如果查询结果为null，则返回null。
     * 
     * @param sql
     * @param parameters
     * @param rowMapper
     *            将返回的结果转化为指定的类型
     * @return
     */
    public Object nativeFindUnique(String sql,
                                   Object[] parameters,
                                   RowMapper rowMapper);
    
    /**
     * 唯一值查询
     * <p/>
     * 根据指定的sql和查询参数（参数为对象数组，sql中的动态参数为?）进行查询
     * <p/>
     * 返回查询结果中的第一条数据，如果查询结果为null，则返回null。
     * 
     * @param sql
     * @param parameters
     * @param rowMapper
     *            将返回的结果转化为指定的类型
     * @return
     */
    public Object nativeFindFirst(String sql,
                                  Object[] parameters,
                                  RowMapper rowMapper);
    
    /**
     * 分页查询
     * <p/>
     * 根据指定的sql和查询参数（参数为对象数组，sql中的动态参数为?）进行查询，并根据查询的范围参数对查询结果进行过滤，
     * <p/>
     * 系统会自动根据指定的sql语句计算出对应的计数语句，在查询的时候对结果集进行统计（对应到Page的totalDataCount属性值）。
     * 
     * @param sql
     * @param parameters
     * @param startPageNo
     * @param maxResultInPage
     * @param rowMapper
     *            将返回的结果转化为指定的类型
     * @return
     */
    public IPage nativeFindPage(String sql,
                               Object[] parameters,
                               int startPageNo,
                               int maxResultInPage,
                               RowMapper rowMapper);
    
    /**
     * 分页查询
     * <p/>
     * 根据指定的sql和查询参数（参数为对象数组，sql中的动态参数为?）进行查询，并根据查询的范围参数对查询结果进行过滤，
     * <p/>
     * 用户必须提供sql查询语句对应的计数语句，这种场景下系统会使用用户提供的计数语句对结果集进行统计（
     * 对应到Page的totalDataCount属性值）。
     * 
     * @param sql4count
     * @param sql4list
     * @param parameters
     * @param startPageNo
     * @param maxResultInPage
     * @param rowMapper
     *            将返回的结果转化为指定的类型
     * @return
     */
    public IPage nativeFindPage(String sql4count,
                               String sql4list,
                               Object[] parameters,
                               int startPageNo,
                               int maxResultInPage,
                               RowMapper rowMapper);
    
    /**
     * 执行udpate或者delete操作，参数为对象数组，数组成员依次对应到sql中的?动态参数
     * 
     * @param sql
     * @param parameters
     * @return
     */
    public int nativeExecute(String sql, Object[] parameters);
    
}
